iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
Modern Web

JS30 x 鐵人30 x MDN doc系列 第 5

[Day5] - Flex Panel Gallery(JS30 x 鐵人 30 x MDN)

  • 分享至 

  • xImage
  •  

實做一個圖片畫廊,當使用者點擊圖片時畫面會聚焦那張圖片(圖片佔比增加),再次點擊會恢復

觀察 index-Start.html👇,會發現排版完全是Normal Flow ,元素預設的排列方式,我們要如何做到與成品一樣的水平排列呢,那就必須變更元素的display 展示系統,如果對 display 基本種類還不太熟悉的朋友,別忘了 MDN、W3C 先去逛爛再說。

要達到水平排列的方式其實不少,「inline-block」、「flex」、「grid」其實都可以做到,語法要下哪些及位置要下在哪裡各有不同,推薦大家都嘗試一下,要練習後面兩種排版系統,這邊推薦兩個網站Flexbox Froggy - A game for learning CSS flexboxGrid Garden - A game for learning CSS grid,透過小遊戲的方式學會這些排版系統,這應該是前端人學習路上必訪的網站之一了。既然題目都叫做「Flex Panel Gallery」,那...

  1. 首先我們先將包含所有 panel 的 div 容器 panels 設定為 flex 容器,並設定排列方式為 row 橫向排列
.panels {
  /*原css再新增*/
  display: flex;
  flex-direction: row;
}

  1. 是變橫向了,但你可能又會要求為什麼沒有佔滿螢幕、沒有均分,No problem!,這邊來強推 flex box 的三法寶「flex-grow 增長比」「flex-shrink 壓縮比」「flex-basis 基本值」,詳細介紹請參考 MDN,請務必搞懂,這裡只要將身為 flex 容器的子元素 Flex Item全部 panel 們,都設定 flex-grow 為 1,那麼他們就會均分剩餘空間,公式如下:
    剩餘空間為100%÷(每個flex item設定的flex-grow值總和)x自身flex-grow值
    100% ÷ (1+1+1+1+1) x 1 = 20%(每個panel元素分得的剩餘空間)
.panel {
  /*原css再新增*/
  flex-grow: 1;
}

  1. 接著為了要讓 panel 內的 3 個<p> tag垂直置中,我們也讓 panel 變成 flex 容器、設定主軸改為垂直排列、內部 item 沿著主軸置中
.panel {
  /*原css再新增*/
  display: flex;
  flex-direction: column;
  justify-content: center;
}

  1. 重複上面所學的,要讓 panel 內的所有元素,平均分配父容器(panel)垂直剩餘空間,且對內要水平、垂直置中,一樣先變成 flex 容器,內部延主軸、交錯軸置中
.panel > * {
  /*原css再新增*/
  display: flex;
  justify-content: center;
  align-items: center;
  flex-grow: 1;
}

  1. 以上基本的CSS終於設定完成,接著要來做點擊會變大再點擊會縮小的功能,觀察作者提供的 css 可以發現.panel.open {font-size: 40px;}特別白話的這個選擇器,依據前幾天的經驗,可想而知作者想要我們透過 Javascript 監聽點擊事件並將節點掛上open這個 class 來讓樣式產生變化,這次我們使用到新的DOMTokenList: toggle() method,正如字面上「切換」的意思,每次執行時判斷 classList 中是否有open這個 class 如果沒有就加上去、如果已經有了就拔掉。
const nodList = document.querySelectorAll(".panel");
nodList.forEach((node) =>
  node.addEventListener("click", (e) => node.classList.toggle("open"))
);

  1. 到上面為止點擊效果也算完成,字體會放大,但寬度好像還不太夠,總不能完全靠字體撐開容器,font-size 可能要設定到 140px 才有作者的視覺效果,這時候不要忘了 flex-grow,我們將擁有openclass 的 item 的 flex-grow 值覆蓋為 5,這樣他的分配剩餘空間比率就會增加,看起來是不是越來越有樣子了 👇
.panel.open {
  flex-grow: 5;
  font-size: 40px;
}

  1. 最後的最後來設定每個 panel 內第一個和最後一個<p>元素的滑入 css,這次我們使用到:first-child&:last-child偽類選擇器取得指定他們,並分別設定在沒有點擊打開的狀態下,第一個垂直向上位移自身高度-100%、最後一個垂直向下位移自身高度 100%,並在掛上openclass 時清除位移,搭配上作者寫好的transition: transform 0.5s指定轉換完成時間即可達到視覺上的滑入效果。
.panel p:first-child {
  transform: translateY(-100%);
}
.panel p:last-child {
  transform: translateY(100%);
}
.panel.open p:first-child,
.panel.open p:last-child {
  transform: unset;
}

完成效果約如文章頂部的 GIF,與 JS30 作者的 finished.html 略有差異,還請各位閱倌自行斟酌及比較 🙏🙏🙏

👉Github Demo 頁面 👈

👉 好想工作室 15th 鐵人賽看板 👈

參考資料

  1. Javascript 30 官網
    https://javascript30.com/
  2. MDN 官網
    https://developer.mozilla.org/en-US/

上一篇
[Day4] - Array Cardio part1(JS30 x 鐵人 30 x MDN)
下一篇
[Day6] - Type Ahead(JS30 x 鐵人 30 x MDN)
系列文
JS30 x 鐵人30 x MDN doc30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言